package com.itestor.iptv.utils;

import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;

import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.Converter;
import org.apache.log4j.Logger;

/**
 * 利用BeanUtils进行Bean转换.
 */
public class BeanConverter {

	/**
	 * convertUtils.
	 */
	private static ConvertUtilsBean convertUtils = new ConvertUtilsBean();

	/**
	 * dateConverter.
	 */
	private static DateConverter dateConverter = new BeanConverter().new DateConverter();

	/**
	 * beanUtils.
	 */
	private static BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils,
			new PropertyUtilsBean());

	static {
		convertUtils.register(dateConverter, Date.class);
	}

	/**
	 * Logger for this class.
	 */
	private static final Logger logger = Logger.getLogger(BeanConverter.class);

	/**
	 * 将MAP中的值转化为BEAN对象.
	 * 
	 * @param bean
	 *            bean
	 * @param map
	 *            map
	 */
	public static void populate(Object bean, Map map) {
		try {
			beanUtils.populate(bean, map);
		} catch (IllegalAccessException e) {
			logger.error("IllegalAccessException:", e);
		} catch (InvocationTargetException e) {
			logger.error("InvocationTargetException:", e);
		}
	}

	/**
	 * 在不同层之间进行属性的拷贝.
	 * 
	 * @param newBean
	 *            newBean
	 * @param bean
	 *            bean
	 */
	public static void copyProperties(Object newBean, Object bean) {
		try {
			BeanUtils.copyProperties(newBean, bean);
		} catch (IllegalAccessException e) {
			logger.error("IllegalAccessException:", e);
		} catch (InvocationTargetException e) {
			logger.error("InvocationTargetException:", e);
		}
	}

	/**
	 * java.util.Date Converter.
	 * 
	 * @author TrueOrFalse.Yuan
	 */
	public final class DateConverter implements Converter {

		/**
		 * The default value specified to our Constructor, if any.
		 */
		private Object defaultValue = null;

		/**
		 * Should we return the default value on conversion errors?
		 */
		private boolean useDefault = true;

		/**
		 * Create a {@link Converter} that will throw a
		 * {@link ConversionException} if a conversion error occurs.
		 */
		public DateConverter() {
			this.defaultValue = null;
			this.useDefault = false;
		}

		/**
		 * Create a {@link Converter} that will return the specified default
		 * value if a conversion error occurs.
		 * 
		 * @param pDefaultValue
		 *            The default value to be returned
		 */
		public DateConverter(Object pDefaultValue) {
			this.defaultValue = pDefaultValue;
			this.useDefault = true;
		}

		/**
		 * Convert the specified input object into an output object of the
		 * specified type.
		 * 
		 * @param type
		 *            Data type to which this value should be converted
		 * @param value
		 *            The input value to be converted
		 * @return Object The Object converted
		 */
		@SuppressWarnings("deprecation")
		public Object convert(Class type, Object value) {

			if (value == null) {
				if (useDefault) {
					return (defaultValue);
				} else {
					throw new ConversionException("No value specified");
				}
			}

			if (value instanceof Date) {
				return (value);
			}

			try {
				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
				return (dateFormat.parse(value.toString()));
			} catch (Exception e) {
				if (useDefault) {
					return (defaultValue);
				} else {
					throw new ConversionException(e);
				}
			}

		}

	}
}
